package rabgame

import (
	"gitee.com/rainbowserver_go/config"
	"github.com/Unknwon/goconfig"
	"github.com/labstack/gommon/log"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"reflect"
	"strings"
)

type CarGameInfo struct {
	mongodb      *mgo.Session
	db           *mgo.Database
	carGameTable *mgo.Collection
	carBetTable  *mgo.Collection
	carSortTable *mgo.Collection
}

type CarGame struct {
	Gameid     int64
	Game       int8
	Number     int8
	Pool       string
	Peoples    int16
	Createtime int32
}

type CarBet struct {
	Id       int64
	Gameid   int64
	Userid   int64
	User     string
	Digital  int8
	Quantity string
	Reward   string
	Bettime  int32
}

type BetSort struct {
	Date string
	User string
	Bets int
}

func (info *CarGameInfo) Init() {
	cfg, _ := goconfig.LoadConfigFile(config.CONFIG_FILE_NAME)
	mongocfg, _ := cfg.GetSection("mongodb")
	url := "mongodb://" + mongocfg["user"] + ":" + mongocfg["pass"] + "@" + mongocfg["host"] + ":" + mongocfg["port"] + "/" + mongocfg["db"]
	mongodb, err := mgo.Dial(url)
	if err != nil {
		log.Fatal(err)
	}
	//defer mongodb.Close()
	mongodb.SetMode(mgo.Monotonic, true)
	info.mongodb = mongodb
	info.db = mongodb.DB(mongocfg["db"])
	info.carGameTable = info.db.C("cargame")
	info.carBetTable = info.db.C("carbet")
	info.carSortTable = info.db.C("carbet_sort")
}

func (info *CarGameInfo) InsertBetSort(date string, user string, bets int) error {
	// { "date": 1, "user": 1 }
	return info.carSortTable.Insert(BetSort{date, user, bets})
}

func (info *CarGameInfo) ModifyBetSort(date string, user string, bets int) error {
	selector := bson.M{"date": date, "user": user}
	data := bson.M{"$set": bson.M{"date": date, "user": user, "bets": bets}}
	err := info.carSortTable.Update(selector, data)
	return err
}

func (info *CarGameInfo) GetBetSort(date string) []map[string]interface{} {
	result := []BetSort{}
	var iter *mgo.Iter

	iter = info.carSortTable.Find(bson.M{"date": date}).Sort("-bets").Iter()

	err := iter.All(&result)
	if err != nil {
		return nil
	} else {
		res := make(map[string]interface{})
		var data []map[string]interface{}
		for i := 0; i < len(result); i++ {
			res = Struct2Map(result[i])
			data = append(data, res)
		}
		return data
	}

	return nil
}

func (info *CarGameInfo) InsertBet(id int64, gameid int64, userid int64, user string, digital int8, quantity string, reward string, bettime int32) error {
	//{ "gameid": 1, "userid": 1, "bettime": 1 }
	cargame := CarBet{id, gameid, userid, user, digital, quantity, reward, bettime}
	err := info.carBetTable.Insert(&cargame)
	return err
}

func (info *CarGameInfo) ModifyBet(id int64, gameid int64, userid int64, user string, digital int8, quantity string, reward string, bettime int32) error {
	selector := bson.M{"gameid": gameid, "userid": userid, "bettime": bettime}
	data := bson.M{"$set": bson.M{"id": id, "gameid": gameid, "userid": userid, "user": user, "digital": digital, "quantity": quantity, "reward": reward, "bettime": bettime}}

	err := info.carBetTable.Update(selector, data)
	return err
}

func (info *CarGameInfo) GetBetList(gameId int64, user string, limit int) []map[string]interface{} {
	result := []CarBet{}
	var iter *mgo.Iter

	if gameId == 0 && user != "" {
		iter = info.carBetTable.Find(bson.M{"user": user}).Limit(limit).Sort("-bettime").Iter()
	} else if gameId > 0 && user == "" {
		iter = info.carBetTable.Find(bson.M{"gameid": gameId}).Limit(limit).Sort("-bettime").Iter()
	} else if gameId > 0 && user != "" {
		iter = info.carBetTable.Find(bson.M{"gameid": gameId, "user": user}).Limit(limit).Sort("-bettime").Iter()
	} else {
		iter = info.carBetTable.Find(bson.M{}).Limit(limit).Sort("-bettime").Iter()
	}

	err := iter.All(&result)
	if err != nil {
		return nil
	} else {
		res := make(map[string]interface{})
		var data []map[string]interface{}
		for i := 0; i < len(result); i++ {
			res = Struct2Map(result[i])
			data = append(data, res)
		}
		return data
	}

	return nil
}

func (info *CarGameInfo) InsertGame(gameId int64, game int8, number int8, pool string, peoples int16, createtime int32) error {
	gameIdIndex := mgo.Index{
		Key:        []string{"gameid"},
		Unique:     true,
		Background: false,
		Sparse:     false,
	}

	createtimeIndex := mgo.Index{
		Key:        []string{"createtime"},
		Unique:     false,
		Background: false,
		Sparse:     false,
	}
	info.carGameTable.EnsureIndex(gameIdIndex)
	info.carGameTable.EnsureIndex(createtimeIndex)
	cargame := CarGame{gameId, game, number, pool, peoples, createtime}
	return info.carGameTable.Insert(&cargame)
}

func (info *CarGameInfo) ModifyGame(gameId int64, game int8, number int8, pool string, peoples int16, createtime int32) error {
	selector := bson.M{"gameid": gameId}
	data := bson.M{"$set": bson.M{"game": game, "number": number, "pool": pool, "peoples": peoples, "createtime": createtime}}
	return info.carGameTable.Update(selector, data)
}

func (info *CarGameInfo) GetGame(gameId int64) map[string]interface{} {
	result := CarGame{}
	err := info.carGameTable.Find(bson.M{"gameid": gameId}).One(&result)
	if err == nil {
		return Struct2Map(result)
	}

	return nil
}

func (info *CarGameInfo) GetGameList(limit int) []map[string]interface{} {
	result := []CarGame{}
	iter := info.carGameTable.Find(bson.M{}).Limit(limit).Sort("-createtime").Iter()
	err := iter.All(&result)
	if err != nil {
		return nil
	} else {
		res := make(map[string]interface{})
		var data []map[string]interface{}
		for i := 0; i < len(result); i++ {
			res = Struct2Map(result[i])
			data = append(data, res)
		}
		return data
	}

	return nil
}

func Struct2Map(obj interface{}) map[string]interface{} {
	t := reflect.TypeOf(obj)
	v := reflect.ValueOf(obj)

	var data = make(map[string]interface{})
	for i := 0; i < t.NumField(); i++ {
		data[strings.ToLower(t.Field(i).Name)] = v.Field(i).Interface()
	}
	return data
}
